package org.jeecg.modules.driver;

import lombok.extern.slf4j.Slf4j;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.codehaus.jettison.json.JSONTokener;
import org.jeecg.boot.starter.rabbitmq.client.RabbitMqClient;
import org.jeecg.modules.commu.ClientConnection;
import org.jeecg.modules.commu.ConnectionFactory;
import org.jeecg.modules.commu.CustomWebSocketListener;
import org.jeecg.modules.device.Device;
import org.jeecg.modules.util.ByteUtils;
import org.jeecg.modules.util.DeviceMsgHelper_PD1_0;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

@Slf4j
public class DriverPortocal1_0 extends DeviceDriver {

    List<CustomWebSocketListener> customWebSocketListenerList  = new ArrayList<CustomWebSocketListener>();

    public DriverPortocal1_0(Device device, ClientConnection conn, RabbitMqClient client) {
        super(device,conn, client);
    }

    public final static String ENCODING = "iso-8859-1";

    @Override
    public boolean runCommand(String command, JSONObject jsonData)  {
        try {
            if (command.equals(DriverCommandList.LOGIN)) {
//            byte[] data = ByteUtils.byteMerger(new byte[]{(byte)password.getBytes().length},password.getBytes());
                byte[] data = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
                byte[] apdu = {(byte) 0xFC, 0x0B, 0x00, 0x00, (byte) data.length}; //APDU
                byte[] merge = ByteUtils.byteMerger(apdu, data);
                String msg = new String(merge, ENCODING);
                connection.sendData(msg);
                return true;
            } else if (command.equals(DriverCommandList.DISCONNECT)) {
                connection.disconnect();
                return true;
            } else if (command.equals(DriverCommandList.SET_DEVICE_CHANNEL_SWITCH)) {
                JSONArray arr = jsonData.getJSONObject("switches").getJSONArray("switches");
                byte[] sendData = new byte[64];
                byte[] apdu = {(byte) 0xFC, 0x09, 0x01, 0x00, (byte) sendData.length};
                for (int i = 0; i < arr.length(); i++) {
                    sendData[i * 2] = 0x00;
                    sendData[i * 2 + 1] = (byte) Integer.parseInt(arr.getJSONObject(i).getString("state"));
                }
                byte[] merge = ByteUtils.byteMerger(apdu, sendData);
                String msg = new String(merge, ENCODING);
                connection.sendData(msg);
                return true;
            } else if (command.equals(DriverCommandList.SET_DEVICE_CHANNEL_CURRENT)) {
                JSONArray arr = jsonData.getJSONObject("switches").getJSONArray("switches");
                byte[] sendData = new byte[64];
                byte[] apdu = {(byte) 0xFC, 0x09, 0x02, 0x00, (byte) sendData.length};
                for (int i = 0; i < arr.length(); i++) {
                    short shortD = (short) (Float.parseFloat(arr.getJSONObject(i).getString("controlC")) * 10);
                    byte[] byteArr = ByteUtils.shortToByteArray(shortD);
                    sendData[i * 2] = byteArr[0];
                    sendData[i * 2 + 1] = byteArr[1];
                }
                byte[] merge = ByteUtils.byteMerger(apdu, sendData);
                String msg = new String(merge, ENCODING);
                connection.sendData(msg);
                return true;
            } else if (command.equals(DriverCommandList.SET_DEVICE_CONFIG)) {

                byte[] sendData = new byte[14];
                byte[] apdu = {(byte) 0xFC, 0x07, 0x00, 0x00, (byte) sendData.length};
                JSONObject baseinfo = jsonData.getJSONObject("baseinfo");
                String[] shortDataStr = new String[]{baseinfo.getString("mainVolMax"), baseinfo.getString("mainVolMin"), baseinfo.getString("mainCurMax"),
                        baseinfo.getString("backVolMax"), baseinfo.getString("backVolMin"), baseinfo.getString("tempMax"), baseinfo.getString("fanTempMax")};
                for (int i = 0; i < shortDataStr.length; i++) {
                    short shortD = (short) (Float.parseFloat(shortDataStr[i]) * 10);
                    byte[] byteArr = ByteUtils.shortToByteArray(shortD);
                    sendData[i * 2] = byteArr[0];
                    sendData[i * 2 + 1] = byteArr[1];
                }
                byte[] merge = ByteUtils.byteMerger(apdu, sendData);
                String msg = new String(merge, ENCODING);
                connection.sendData(msg);
                return true;
            }
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }catch(JSONException eJson){
            eJson.printStackTrace();
        }
        log.error("Command '"+command+"' not support by "+ this.getClass().getName() );
        return false;
    }


    @Override
    public Device resolveCommand(String d_cmd, String msg) {
        try {
            boolean stateChange = true;
            JSONObject shadow = device.getShadow();
            JSONObject oldData = new JSONObject(new JSONTokener(shadow.toString()));
            log.info("===============resolveCommand====================cmd:"+d_cmd+"    msg:" + msg);
            if (d_cmd.equals(DriverCommandList.D_LOCAL_CONNECTED)) {
                shadow = DeviceMsgHelper_PD1_0.deviceConnected(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceBase)) { //SN,MAC,MODEL,TYPE
                shadow = DeviceMsgHelper_PD1_0.anaylysBaseInfo(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceCurrent)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceCurrent(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceCurrentLimit)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceCurrentLimit(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceDhcpIpPort)) {
                //禁止处理和修改网络信息，避免下位机修改了设备，上位机记录了然后直接又重连了，占用了新的IP和端口
                //fix：20230917
                //shadow = DeviceMsgHelper_PD1_0.anaylysDeviceDhcpIpPort(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceGateway)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceGateway(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceMac)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceMac(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceMainStatus)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceMainStatus(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceSetConfig)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceSetConfig(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceSubnetMask)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceSubnetMask(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceSwitch)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceSwitch(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceWanringChannel)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceWanringChannel(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_deviceWarningDevice)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceWarningDevice(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_DeviceDNS)) {
                shadow = DeviceMsgHelper_PD1_0.anaylysDeviceDNS(shadow, msg);
            } else if (d_cmd.equals(DriverCommandList.D_LOCAL_DISCONNECT)) {
              //Not reachable
                stateChange = false;
            } else if (d_cmd.equals(DriverCommandList.ACK)) {
                stateChange = false;
                //6C 参数错误,67 长度错误 , 90 成功
                shadow.put("cmd", "ack");
                byte msgByte = msg.getBytes(ENCODING)[0];
                if (msgByte == (byte) 0x90)
                    shadow.put("cmdStr", "");
                else if (msgByte == (byte) 0x6C || msgByte == (byte) 0x67)
                    shadow.put("cmdStr", "发送命令错误");
            } else {
                stateChange = false;
                log.error("Device command not supported " + d_cmd);
            }
            shadow.put("cmd", d_cmd);
            shadow.put("cmdTime", Calendar.getInstance().getTime().getTime());
            device.setOldData(oldData);
            if(stateChange){
                //TODO:Websocket 注入到这个列表里，不放在RabbitMqListner1里
                for (int i = 0; i < customWebSocketListenerList.size(); i++) {
                    customWebSocketListenerList.get(i).pushMessage(device.getId(), shadow.toString());
                }
            }
            return device;
        }catch (Exception eJson){
            eJson.printStackTrace();
            return null;
        }
    }

    @Override
    public void registerMq(RabbitMqClient rabbitMqClient) {
        this.getConnection().registerRabbitMq(rabbitMqClient);
    }

}
